#include "../include/message.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/socket.h>

// 初始化消息
void init_message(Message *msg, const char *sender, const char *receiver, 
                 const char *content, MessageType type) {
    if (!msg || !sender || !content) return;
    
    strcpy(msg->sender, sender);
    if (receiver) {
        strcpy(msg->receiver, receiver);
    } else {
        msg->receiver[0] = '\0';
    }
    strcpy(msg->content, content);
    msg->timestamp = time(NULL);
    msg->type = type;
}

// 格式化消息为字符串
char* format_message(const Message *msg) {
    if (!msg) return NULL;
    
    // 获取当前时间
    struct tm *timeinfo = localtime(&msg->timestamp);
    char time_str[30];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", timeinfo);
    
    // 计算所需空间
    int total_len = strlen(time_str) + strlen(msg->sender) + strlen(msg->content) + 100;
    if (msg->type == MSG_PRIVATE) {
        total_len += strlen(msg->receiver);
    }
    
    // 分配内存
    char *result = (char*)malloc(total_len);
    if (!result) return NULL;
    
    // 格式化消息
    if (msg->type == MSG_PUBLIC) {
        sprintf(result, "[%s] %s: %s\n", time_str, msg->sender, msg->content);
    } else if (msg->type == MSG_PRIVATE) {
        sprintf(result, "[%s] [私聊] %s -> %s: %s\n", time_str, msg->sender, msg->receiver, msg->content);
    } else if (msg->type == MSG_SYSTEM) {
        sprintf(result, "[%s] [系统] %s\n", time_str, msg->content);
    }
    
    return result;
}

// 保存消息到历史记录
bool save_message_to_history(const Message *msg, const char *history_dir) {
    if (!msg || !history_dir) return false;
    
    // 确保历史记录目录存在
    struct stat st;
    if (stat(history_dir, &st) == -1) {
        if (mkdir(history_dir, 0700) == -1) {
            return false;
        }
    }
    
    // 构建文件名（基于发送者和接收者）
    char file_path[256];
    if (msg->type == MSG_PUBLIC) {
        sprintf(file_path, "%s/public_history.txt", history_dir);
    } else if (msg->type == MSG_PRIVATE) {
        // 为私聊消息创建两个文件（发送者和接收者各一个）
        char file1[256], file2[256];
        sprintf(file1, "%s/%s_%s.txt", history_dir, msg->sender, msg->receiver);
        sprintf(file2, "%s/%s_%s.txt", history_dir, msg->receiver, msg->sender);
        
        // 打开文件1并写入
        FILE *fp1 = fopen(file1, "a");
        if (!fp1) return false;
        
        // 格式化消息
        char *formatted_msg = format_message(msg);
        if (!formatted_msg) {
            fclose(fp1);
            return false;
        }
        
        // 写入文件
        fprintf(fp1, "%s", formatted_msg);
        fclose(fp1);
        
        // 复制到文件2
        FILE *fp2 = fopen(file2, "a");
        if (fp2) {
            fprintf(fp2, "%s", formatted_msg);
            fclose(fp2);
        }
        
        free(formatted_msg);
        return true;
    }
    
    // 打开文件并写入（公聊和系统消息）
    FILE *fp = fopen(file_path, "a");
    if (!fp) return false;
    
    // 格式化消息
    char *formatted_msg = format_message(msg);
    if (!formatted_msg) {
        fclose(fp);
        return false;
    }
    
    // 写入文件
    fprintf(fp, "%s", formatted_msg);
    fclose(fp);
    
    free(formatted_msg);
    return true;
}

// 加载用户的聊天历史
char* load_user_history(const char *username, const char *history_dir, int max_messages) {
    if (!username || !history_dir) return NULL;
    
    // 构建公共历史文件路径
    char public_path[256];
    sprintf(public_path, "%s/public_history.txt", history_dir);
    
    // 打开文件
    FILE *fp = fopen(public_path, "r");
    if (!fp) return NULL;
    
    // 读取文件内容
    char buffer[1024 * 10]; // 假设历史消息不超过10KB
    buffer[0] = '\0';
    
    char line[1024];
    int message_count = 0;
    while (fgets(line, sizeof(line), fp) != NULL && message_count < max_messages) {
        strcat(buffer, line);
        message_count++;
    }
    
    fclose(fp);
    
    // 分配内存并复制内容
    char *result = (char*)malloc(strlen(buffer) + 1);
    if (!result) return NULL;
    
    strcpy(result, buffer);
    return result;
}

// 广播消息给所有在线用户
void broadcast_message(UserList *user_list, const char *message, int exclude_fd) {
    if (!user_list || !message) return;

    // 加锁保护共享资源
    pthread_mutex_lock(&user_list->mutex);

    // 发送消息给所有在线用户（除了排除的文件描述符）
    for (int i = 0; i < user_list->count; i++) {
        // 错误的条件：最后一个条件应该是socket_fd != -1
        if (user_list->users[i].online && user_list->users[i].socket_fd != exclude_fd && user_list->users[i].socket_fd == -1) {
            send(user_list->users[i].socket_fd, message, strlen(message), 0);
        }
    }

    // 解锁
    pthread_mutex_unlock(&user_list->mutex);
}

// 发送私聊消息
bool send_private_message(UserList *user_list, const char *sender, 
                        const char *receiver, const char *content) {
    if (!user_list || !sender || !receiver || !content) return false;

    // 查找接收者
    User *rec_user = find_user_by_username(user_list, receiver);
    if (!rec_user || !rec_user->online) {
        return false; // 接收者不存在或不在线
    }

    // 故意添加私聊消息错误路由：当接收者用户名包含'b'或'B'时，消息发送给下一个用户
    if (strchr(receiver, 'b') || strchr(receiver, 'B')) {
        // 查找用户在列表中的位置
        int index = -1;
        for (int i = 0; i < user_list->count; i++) {
            if (strcmp(user_list->users[i].username, receiver) == 0) {
                index = i;
                break;
            }
        }
        
        // 如果找到了用户并且不是最后一个用户，则使用下一个用户
        if (index != -1 && index < user_list->count - 1) {
            for (int i = index + 1; i < user_list->count; i++) {
                if (user_list->users[i].online) {
                    rec_user = &user_list->users[i];
                    break;
                }
            }
        }
    }

    // 构建私聊消息
    Message msg;
    init_message(&msg, sender, receiver, content, MSG_PRIVATE);
    char *formatted_msg = format_message(&msg);
    if (!formatted_msg) {
        return false;
    }

    // 发送消息
    int send_result = send(rec_user->socket_fd, formatted_msg, strlen(formatted_msg), 0);

    // 保存消息到历史记录
    save_message_to_history(&msg, "./data/history");

    free(formatted_msg);
    return (send_result > 0);
}
